using System.Collections.Generic;
using System;
using System.Net.Mail;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Web.Configuration;
using System.Net.Configuration;

using WikiPlex;
using WikiPlex.Formatting;

using MvcCms.Service.Code.Wiki;
using MvcCms.Data;
using MvcCms.Service;
using MvcCms.Service.Cache;
using MvcCms.Service.Logging;
using Microsoft.Practices.ServiceLocation;
using MvcCms.Service.Code.Membership;

namespace MvcCms.Service.Code.Email
{
    public class MailDeliveryResult
    {
        public bool Success { get; set; }
        public Exception Exception { get; set; }
    }
    public static class MvcCmsEmails
    {
        public static string EmptyInValidEmail(string email)
        {
            try
            {
                if (!string.IsNullOrEmpty(email))
                {
                    var addr = new System.Net.Mail.MailAddress(email);
                }
                return email;
            }
            catch
            {
                ICacheService cacheService = ServiceLocator.Current.GetInstance<ICacheService>();
                Portal portal = cacheService.GetCurrentPortal();
                DynamicEmail("Email Address Problem", portal.AdminEmail, portal.AdminEmail, "Could not email " + email);
                return string.Empty;
            }
        }
        public static MailDeliveryResult SendMessage(string recipientEmail, MailMessage message)
        {
            message.To.Clear();
            message.To.Add(recipientEmail);

            var smtpClient = new SmtpClient();
            
            
            message.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
            try
            {
                smtpClient.Send(message);
                return new MailDeliveryResult()
                {
                    Success = true
                };
            }
            catch (Exception ex)
            {
                return new MailDeliveryResult()
                {
                    Success = false,
                    Exception = ex
                };
            }
        }
        public static void Welcome(User userToWelcome)
        {
            string NotSentRecipients = "";

            ICacheService cacheService = ServiceLocator.Current.GetInstance<ICacheService>();
            var portalService = ServiceLocator.Current.GetInstance<IPortalService>();
            var wikiEngine = ServiceLocator.Current.GetInstance<IWikiEngine>();

            Portal portal = cacheService.GetCurrentPortal();
            MailDefinition emailTemplate = null;
            if (portal.IsRazor)
            {
                emailTemplate = new MailDefinition
                {
                    BodyFileName =
                        "~/razorthemes/" + portal.SkinName + "/templates/Email-Welcome.htm",
                    From = portal.AdminEmail
                };
            }
            else
            {
                emailTemplate = new MailDefinition
                {
                    BodyFileName =
                        "~/content/app_themes/" + portal.SkinName + "/templates/Email-Welcome.htm",
                    From = portal.AdminEmail
                };
            }

            var data = new Dictionary<string, string>
            {
               {"<<user.UserName>>", userToWelcome.UserName},
               {"<<url>>", "http://" + portal.URLAuthority}
            };

            MailMessage message = emailTemplate.CreateMailMessage(userToWelcome.Email, data, new LiteralControl());
            message.IsBodyHtml = true;
            message.Subject = string.Format("Welcome to " + portal.DisplayName);

            var templates = portalService.ListEmailTemplates();
            if (templates.Count() > 0)
            {
                var template = templates.Where(
                    t => t.Name == "Welcome")
                    .FirstOrDefault();
                if (template != null)
                {
                    message.Body = "<html><head></head><body>";
                    message.Body += HttpUtility.HtmlDecode(wikiEngine.Render(template.Body, GetFormatter()));
                    message.Body += "</body></html>";
                    // Replace placeholders in template.
                    message.Body = message.Body.Replace("<<user.username>>", userToWelcome.UserName);
                    message.Body = message.Body.Replace("<<url>>", portal.URLAuthority);
                    message.Body = message.Body.Replace("<<portal.adminemail>>", portal.AdminEmail);
                }
            }

            message.CC.Add(new MailAddress(portal.AdminEmail));

            var smtpClient = new SmtpClient();
            
            
            message.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
            try
            {
                smtpClient.Send(message);
            }
            catch (SmtpFailedRecipientsException ex)
            {
                foreach (Exception innerEx in ex.InnerExceptions)
                {
                    SmtpFailedRecipientException failedRecipEx = innerEx as SmtpFailedRecipientException;
                    if (failedRecipEx != null)
                    {
                        NotSentRecipients += (failedRecipEx.FailedRecipient.Replace("<", "").Replace(">", ""));
                    }
                }
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (SmtpFailedRecipientException ex)
            {
                NotSentRecipients += ex.FailedRecipient.Replace("<", "").Replace(">", "");
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (Exception ex)
            {
                //if you are on iss7 you are probably going to see the below in the error log table, the only way to reproduce is from the server
                //System.Net.Mail.SmtpException: Failure sending mail. ---> System.UnauthorizedAccessException: Access to the path
                //'C:\inetpub\mailroot\Pickup\2e51e5cd-1e8f-4db5-afad-20d12aea7ec8.eml' is denied.
                AppLogging.GetLogger().Error("Emails.cs/Welcome", ex);
            }
        }

        public static void ResetPassword(User user)
        {
            string NotSentRecipients = "";
            ICacheService cacheService = ServiceLocator.Current.GetInstance<ICacheService>();
            Portal portal = cacheService.GetCurrentPortal();
            var portalService = ServiceLocator.Current.GetInstance<IPortalService>();
            var wikiEngine = ServiceLocator.Current.GetInstance<IWikiEngine>();

            string token = PasswordResetToken.GetTokenForValidation(user.Email.ToLower(), user.PasswordAnswer);
            string authenticationUrl = String.Format("{0}?email={1}&token={2}", portal.URLAuthority + "/Account/Validate", HttpUtility.UrlEncode(user.Email), HttpUtility.UrlEncode(token));

            MailDefinition emailTemplate = null;
            if (portal.IsRazor)
            {
                emailTemplate = new MailDefinition
                {
                    BodyFileName =
                        "~/razorthemes/" + portal.SkinName + "/templates/Email-ResetPassword.htm",
                    From = portal.AdminEmail
                };
            }
            else
            {
                emailTemplate = new MailDefinition
                {
                    BodyFileName =
                        "~/content/app_themes/" + portal.SkinName + "/templates/Email-ResetPassword.htm",
                    From = portal.AdminEmail
                };
            }
            var data = new Dictionary<string, string>
            {
               {"<<emailAddress>>", user.Email},
               {"<<passwordLink>>", authenticationUrl}
            };

            MailMessage message = emailTemplate.CreateMailMessage(user.Email, data, new LiteralControl());
            message.IsBodyHtml = true;
            message.Subject = string.Format("Password reset at " + portal.DisplayName);

            var templates = portalService.ListEmailTemplates();
            if (templates.Count() > 0)
            {
                var template = templates.Where(
                    t => t.Name == "ResetPassword")
                    .FirstOrDefault();
                if (template != null)
                {
                    message.Body = "<html><head></head><body>";
                    message.Body += HttpUtility.HtmlDecode(wikiEngine.Render(template.Body, GetFormatter()));
                    message.Body += "</body></html>";
                    // Replace placeholders in template.
                    message.Body = message.Body.Replace("<<emailAddress>>", user.Email);
                    message.Body = message.Body.Replace("<<passwordLink>>", authenticationUrl);
                }
            }

            message.CC.Add(new MailAddress(portal.AdminEmail));

            var smtpClient = new SmtpClient();


            message.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
            try
            {
                smtpClient.Send(message);
            }
            catch (SmtpFailedRecipientsException ex)
            {
                foreach (Exception innerEx in ex.InnerExceptions)
                {
                    SmtpFailedRecipientException failedRecipEx = innerEx as SmtpFailedRecipientException;
                    if (failedRecipEx != null)
                    {
                        NotSentRecipients += (failedRecipEx.FailedRecipient.Replace("<", "").Replace(">", ""));
                    }
                }
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (SmtpFailedRecipientException ex)
            {
                NotSentRecipients += ex.FailedRecipient.Replace("<", "").Replace(">", "");
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error("Emails.cs/ResetPassword", ex);
            }
        }

        public static void CommentReply(ContentComment reply)
        {
            string NotSentRecipients = "";
            ICacheService cacheService = ServiceLocator.Current.GetInstance<ICacheService>();
            Portal portal = cacheService.GetCurrentPortal();
            var portalService = ServiceLocator.Current.GetInstance<IPortalService>();
            var wikiEngine = ServiceLocator.Current.GetInstance<IWikiEngine>();

            string sitename = portal.DisplayName;
            MailDefinition emailTemplate = null;
            if (portal.IsRazor)
            {
                emailTemplate = new MailDefinition
                {
                    BodyFileName =
                        "~/razorthemes/" + portal.SkinName + "/templates/Email-CommentReply.htm",
                    From = portal.AdminEmail
                };
            }
            else
            {
                emailTemplate = new MailDefinition
                {
                    BodyFileName =
                        "~/content/app_themes/" + portal.SkinName + "/templates/Email-CommentReply.htm",
                    From = portal.AdminEmail
                };
            }

            var data = new Dictionary<string, string> { { "<<sitename>>", sitename } };
            string urltmp = "http://" + portal.URLAuthority;

            urltmp += reply.ContentPage.ContentCategory.Path;
            if (reply.ContentPage.IsSubPage)
            {
                urltmp += "/" + reply.ContentPage.Path;
            }
            data.Add("<<pagename>>", reply.ContentPage.Title);
            data.Add("<<user.name>>", reply.User.UserName);
            data.Add("<<url>>", urltmp);
            data.Add("<<reply.body>>", reply.Body);

            MailMessage message = emailTemplate.CreateMailMessage(reply.ParentComment.User.Email, data, new LiteralControl());
            message.IsBodyHtml = true;
            message.Subject = string.Format("Your comment at " + sitename + " has a new reply.");

            var templates = portalService.ListEmailTemplates();
            if (templates.Count() > 0)
            {
                var template = templates.Where(
                    t => t.Name == "CommentReply")
                    .FirstOrDefault();
                if (template != null)
                {
                    message.Body = "<html><head></head><body>";
                    message.Body += HttpUtility.HtmlDecode(wikiEngine.Render(template.Body, GetFormatter()));
                    message.Body += "</body></html>";
                    // Replace placeholders in template.
                    message.Body = message.Body.Replace("<<pagename>>", reply.ContentPage.Title);
                    message.Body = message.Body.Replace("<<user.name>>", reply.User.UserName);
                    message.Body = message.Body.Replace("<<url>>", urltmp);
                    message.Body = message.Body.Replace("<<reply.body>>", reply.Body);
                }
            }

            message.CC.Add(new MailAddress(portal.AdminEmail));

            var smtpClient = new SmtpClient();
            
            
            message.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
            try
            {
                smtpClient.Send(message);
            }
            catch (SmtpFailedRecipientsException ex)
            {
                foreach (Exception innerEx in ex.InnerExceptions)
                {
                    SmtpFailedRecipientException failedRecipEx = innerEx as SmtpFailedRecipientException;
                    if (failedRecipEx != null)
                    {
                        NotSentRecipients += (failedRecipEx.FailedRecipient.Replace("<", "").Replace(">", ""));
                    }
                }
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (SmtpFailedRecipientException ex)
            {
                NotSentRecipients += ex.FailedRecipient.Replace("<", "").Replace(">", "");
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error("Emails.cs/ContentReply", ex);
            }
        }

        public static void NewsLetter(OptInNewsLetter newsLetter, OptInSubscriber subscriber, string footerHTML, Portal portal)
        {
            string NotSentRecipients = "";
            var html = newsLetter.HTML;
            html += footerHTML;
            html = "<html><body>" + html + "</body></html>";

            MailMessage message = new MailMessage(newsLetter.FromEmail, subscriber.EMail, newsLetter.Subject, html);
            
            //var smtpClient = new SmtpClient("email.yourdomain.com", 25);
            //smtpClient.UseDefaultCredentials = true;
            //smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;

            var smtpClient = new SmtpClient();
                        
            message.IsBodyHtml = true;
            message.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");

            try
            {
                smtpClient.Send(message);
            }
            catch (SmtpFailedRecipientsException ex)
            {
                foreach (Exception innerEx in ex.InnerExceptions)
                {
                    SmtpFailedRecipientException failedRecipEx = innerEx as SmtpFailedRecipientException;
                    if (failedRecipEx != null)
                    {
                        NotSentRecipients += (failedRecipEx.FailedRecipient.Replace("<", "").Replace(">", ""));
                    }
                }
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (SmtpFailedRecipientException ex)
            {
                NotSentRecipients += ex.FailedRecipient.Replace("<", "").Replace(">", "");
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error("Emails.cs/NewsLetter", ex);
            }
        }

        public static void DynamicEmail(string title, string from, string to, string body)
        {
            string NotSentRecipients = "";
            var mailMessage = new MailMessage();

            mailMessage.Body = body;
            mailMessage.From = new MailAddress(from);
            mailMessage.Subject = title;
            mailMessage.To.Add(new MailAddress(to));

            var smtpClient = new SmtpClient();
            
            

            try
            {
                smtpClient.Send(mailMessage);
            }
            catch (SmtpFailedRecipientsException ex)
            {
                foreach (Exception innerEx in ex.InnerExceptions)
                {
                    SmtpFailedRecipientException failedRecipEx = innerEx as SmtpFailedRecipientException;
                    if (failedRecipEx != null)
                    {
                        NotSentRecipients += (failedRecipEx.FailedRecipient.Replace("<", "").Replace(">", ""));
                    }
                }
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (SmtpFailedRecipientException ex)
            {
                NotSentRecipients += ex.FailedRecipient.Replace("<", "").Replace(">", "");
                AppLogging.GetLogger().Error(NotSentRecipients, ex);
            }
            catch (Exception ex)
            {
                AppLogging.GetLogger().Error("Emails.cs/DynamicEmail", ex);
            }

        }

        private static MacroFormatter GetFormatter()
        {
            var siteRenderers = new IRenderer[]
            {
                new TitleLinkRenderer(),
                new TextColorRenderer(),
                new TextSizeRenderer(),
                new AnyStyleRenderer(),
            };
            IEnumerable<IRenderer> allRenderers = Renderers.All.Union(siteRenderers);
            return new MacroFormatter(allRenderers);
        }
    }
}